package com.ctshk.rpc.insurance.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ctshk.common.dto.Result;
import com.ctshk.common.enums.*;
import com.ctshk.common.enums.Currency;
import com.ctshk.common.exception.BusinessException;
import com.ctshk.common.model.PageResponse;
import com.ctshk.common.utils.*;
import com.ctshk.rpc.booking.enums.SupplierReserveTypeEnum;
import com.ctshk.rpc.booking.req.system.insurance.add.SupplierOrderSystemInsuranceAddReq;
import com.ctshk.rpc.booking.req.system.insurance.add.SupplierSystemOrderInsuranceAddReq;
import com.ctshk.rpc.booking.req.system.insurance.add.SupplierSystemOrderInsuranceDetailAddReq;
import com.ctshk.rpc.booking.service.ISupplierOrderService;
import com.ctshk.rpc.insurance.dto.*;
import com.ctshk.rpc.insurance.entity.Insurance;
import com.ctshk.rpc.insurance.entity.InsuranceCost;
import com.ctshk.rpc.insurance.entity.InsuranceProduct;
import com.ctshk.rpc.insurance.mapper.InsuranceCostMapper;
import com.ctshk.rpc.insurance.mapper.InsuranceMapper;
import com.ctshk.rpc.insurance.mapper.InsuranceProductMapper;
import com.ctshk.rpc.insurance.properties.TpProperties;
import com.ctshk.rpc.insurance.req.*;
import com.ctshk.rpc.insurance.req.taiping.*;
import com.ctshk.rpc.insurance.req.tp.*;
import com.ctshk.rpc.insurance.req.tp.CancelReq;
import com.ctshk.rpc.insurance.req.tp.Offer;
import com.ctshk.rpc.insurance.req.tp.OfferReq;
import com.ctshk.rpc.insurance.service.IInsuranceService;
import com.ctshk.rpc.insurance.util.PacificUtil;
import com.ctshk.rpc.stamp.dto.LevyDTO;
import com.ctshk.rpc.stamp.req.LevyRequest;
import com.ctshk.rpc.stamp.service.ILevyService;
import com.ctshk.rpc.system.dto.UserDTO;
import com.ctshk.rpc.system.service.ISysUserService;
import com.google.common.collect.Lists;
import io.seata.common.util.CollectionUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.dubbo.config.annotation.DubboService;
import org.apache.http.HttpEntity;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Autowired;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 保险资源 服务实现类
 * </p>
 *
 * @author wangcy
 * @since 2021-01-26
 */
@Slf4j
@DubboService
public class InsuranceServiceImpl extends ServiceImpl<InsuranceMapper, Insurance> implements IInsuranceService {

    @Autowired
    private TpProperties tpProperties;

    @Autowired
    private InsuranceCostMapper insuranceCostMapper;
    @Autowired
    private InsuranceProductMapper productMapper;
    @DubboReference
    private ISupplierOrderService supplierOrderService;
    @DubboReference
    private ISysUserService sysUserService;
    @DubboReference
    private ILevyService levyService;

    @Override
    public PageResponse<InsuranceProductDTO> queryList(InsuranceProductReq insuranceProductReq) {
        IPage<Insurance> iPage = new Page<>(insuranceProductReq.getPageNo(), insuranceProductReq.getPageSize());
        QueryWrapper<Insurance> queryWrapper = new QueryWrapper<>();
        if (CollectionUtils.isNotEmpty(insuranceProductReq.getIds())) {
            queryWrapper.lambda().in(Insurance::getId, insuranceProductReq.getIds());
        }
        if (StringUtils.isNotBlank(insuranceProductReq.getName())) {
            queryWrapper.lambda().like(Insurance::getName, insuranceProductReq.getName());
        }
        if (null != insuranceProductReq.getStatus()) {
            queryWrapper.lambda().eq(Insurance::getStatus, insuranceProductReq.getStatus());
        }
        /*if (StringUtils.isNotBlank(insuranceProductReq.getApplicableServices())) {
            queryWrapper.apply(insuranceProductReq.getApplicableServices() != null, "FIND_IN_SET (" + insuranceProductReq.getApplicableServices() + ",applicable_services)");
        }*/
        queryWrapper.lambda().eq(Insurance::getIsDeleted, IsDeletedCode.NO.getCode())
                .orderByDesc(Insurance::getGmtCreate)
                .select(Insurance::getId, Insurance::getName, Insurance::getSourceType, Insurance::getCompanyName, Insurance::getProductTrait,
                        Insurance::getApplicableServices, Insurance::getStatus, Insurance::getGmtCreate);
        IPage<Insurance> insuranceIPage = baseMapper.selectPage(iPage, queryWrapper);

        if (CollectionUtils.isNotEmpty(insuranceIPage.getRecords())) {
            List<InsuranceProductDTO> insuranceProductDTOList = EntityUtil.copyList(insuranceIPage.getRecords(), InsuranceProductDTO.class);
            return new PageResponse<>(insuranceProductDTOList, iPage.getCurrent() == 1, iPage.getTotal() <= (iPage.getCurrent() * iPage.getSize()), iPage.getTotal(), iPage.getCurrent(), iPage.getSize());
        }
        return new PageResponse<>(new ArrayList<>(), iPage.getCurrent() == 1, iPage.getTotal() <= (iPage.getCurrent() * iPage.getSize()), iPage.getTotal(), iPage.getCurrent(), iPage.getSize());
    }

    @Override
    public PageResponse<InsuranceGroupPageDTO> queryGroupList(InsuranceGroupPageReq insuranceGroupPageReq) {
        IPage<Insurance> iPage = new Page<>(insuranceGroupPageReq.getPageNo(), insuranceGroupPageReq.getPageSize());
        QueryWrapper<Insurance> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().like(StringUtils.isNotBlank(insuranceGroupPageReq.getName()), Insurance::getName, insuranceGroupPageReq.getName())
                .apply("FIND_IN_SET({0}, applicable_services) ", insuranceGroupPageReq.getInsuranceType())
                .eq(Insurance::getStatus, 1)
                .eq(Insurance::getIsDeleted, IsDeletedCode.NO.getCode())
                .orderByDesc(Insurance::getGmtCreate);
        IPage<Insurance> insuranceIPage = baseMapper.selectPage(iPage, queryWrapper);
        List<Insurance> records = insuranceIPage.getRecords();
        if (CollectionUtils.isNotEmpty(records)) {
            List<InsuranceGroupPageDTO> insuranceBusinessPageDTOS = EntityUtil.copyList(records, InsuranceGroupPageDTO.class);
            return new PageResponse<>(insuranceBusinessPageDTOS, iPage.getCurrent() == 1, iPage.getTotal() <= (iPage.getCurrent() * iPage.getSize()), iPage.getTotal(), iPage.getCurrent(), iPage.getSize());
        }
        return new PageResponse<>(new ArrayList<>(), iPage.getCurrent() == 1, iPage.getTotal() <= (iPage.getCurrent() * iPage.getSize()), iPage.getTotal(), iPage.getCurrent(), iPage.getSize());
    }

    @Override
    public List<InsuranceBusinessPageDTO> queryBusinessList(InsuranceBusinessPageReq insuranceBusinessPageReq, Long userId) {
        QueryWrapper<Insurance> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().like(StringUtils.isNotBlank(insuranceBusinessPageReq.getName()), Insurance::getName, insuranceBusinessPageReq.getName())
                .apply("FIND_IN_SET({0}, applicable_services) ", insuranceBusinessPageReq.getInsuranceType())
                .eq(Insurance::getStatus, 1)
                .eq(Insurance::getIsDeleted, IsDeletedCode.NO.getCode())
                .orderByDesc(Insurance::getGmtCreate);
        List<Insurance> insurances = baseMapper.selectList(queryWrapper);

        if (CollectionUtils.isEmpty(insurances)) {
            return new ArrayList<>();
        }
        List<Long> insuranceIds = insurances.stream().map(Insurance::getId).collect(Collectors.toList());
        List<InsuranceBusinessPageDTO> insuranceBusinessPageDTOS = EntityUtil.copyList(insurances, InsuranceBusinessPageDTO.class);
        // 查询成本价
        List<InsuranceCost> insuranceCosts = insuranceCostMapper.selectList(new QueryWrapper<InsuranceCost>().lambda()
                .in(InsuranceCost::getInsuranceId, insuranceIds)
                .eq(InsuranceCost::getIsDeleted, IsDeletedCode.NO.getCode()));
        // 查询加幅
        List<InsuranceProduct> insuranceProducts = productMapper.selectList(new QueryWrapper<InsuranceProduct>().lambda()
                .in(InsuranceProduct::getInsuranceId, insuranceIds)
                .eq(InsuranceProduct::getIsDeleted, IsDeletedCode.NO.getCode()));
        LocalDateTime localDateTime = LocalDateTime.now();
        List<InsuranceCost> insuranceCostList = new ArrayList<>();
        for (int i = 0; i < insurances.size(); i++) {
            Insurance insurance = insurances.get(i);
            InsuranceCost insuranceCost = insuranceCosts.stream().filter(o -> o.getInsuranceId().equals(insurance.getId())).findAny().orElse(null);
            if (null == insuranceCost) {
                insuranceCost = new InsuranceCost();
            }
            if (null == insuranceCost.getCostAmount()) {
                /**
                 * 查询报价
                 */
                OfferReq offerReq = new OfferReq();
                Offer offer = new Offer();
                offer.setStarDate(DateUtil.fmtLocalDate(insuranceBusinessPageReq.getBeginDate(), "yyyy-MM-dd"));
                offer.setEndDate(DateUtil.fmtLocalDate(insuranceBusinessPageReq.getEndDate(), "yyyy-MM-dd"));
//                    offer.setRiskCode(insurance.getApiCode().concat(insurance.getCtsCode()));
                offer.setRiskCode(insurance.getApiCode());
                offer.setRationType(insurance.getRationType());
                offer.setChildCount((long) insuranceBusinessPageReq.getAdultNum());
                offer.setPersonCount((long) insuranceBusinessPageReq.getChildrenNum());
                offerReq.setData(offer);
                try {
                    OfferDTO offerDTO = acciQuotation(offerReq);
                    if (null != offerDTO) {
                        insuranceCost.setCostAmount(offerDTO.getPremium());
                        if (null == insuranceCost.getId()) {
                            insuranceCost.setId(SnowflakeIdWorker.nextId());
                            insuranceCost.setInsuranceId(insurance.getId());
                            insuranceCost.setCreateId(userId);
                            insuranceCost.setGmtCreate(localDateTime);
                            insuranceCost.setModifiedId(userId);
                            insuranceCost.setGmtModified(localDateTime);
                            insuranceCost.setIsDeleted(IsDeletedCode.NO.getCode());
                            insuranceCostList.add(insuranceCost);
                        } else {
                            insuranceCost.setModifiedId(userId);
                            insuranceCost.setGmtModified(localDateTime);
                            insuranceCostMapper.update(null, new UpdateWrapper<InsuranceCost>().lambda()
                                    .eq(InsuranceCost::getId, insuranceCost.getId())
                                    .set(InsuranceCost::getCostAmount, insuranceCost.getCostAmount())
                                    .set(InsuranceCost::getModifiedId, userId)
                                    .set(InsuranceCost::getGmtModified, localDateTime));
                        }
                    }
                } catch (Exception e) {
                    log.error("【保险-自由行分页查询】查询报价失败，error:{}", e.getMessage(), e);
                }
            }
            //设置加幅价格
            if (null != insuranceCost.getCostAmount()) {
                InsuranceProduct insuranceProduct = insuranceProducts.stream().filter(o -> o.getInsuranceId().equals(insurance.getId())).findAny().orElse(null);
                BigDecimal price = getIncreasePrice(insuranceCost.getCostAmount(), insuranceProduct);
                insuranceBusinessPageDTOS.get(i).setPrice(price);
            }
        }
        if (CollectionUtils.isNotEmpty(insuranceCostList)) {
            insuranceCostMapper.insertBatchSomeColumn(insuranceCostList);
        }
        return insuranceBusinessPageDTOS;

    }

    /**
     * 获取加幅价格
     *
     * @param costAmount
     * @param insuranceProduct
     * @return
     */
    private BigDecimal getIncreasePrice(BigDecimal costAmount, InsuranceProduct insuranceProduct) {
        if (null == insuranceProduct) {
            //成本价
            return costAmount;
        } else if (insuranceProduct.getAdjustType().equals(0)) {
            //数值加幅价
            BigDecimal amount = costAmount.add(insuranceProduct.getAmount());
            return amount;
        } else {
            //百分比加幅价
            BigDecimal bigDecimal = insuranceProduct.getPercent().add(new BigDecimal("1"));
            BigDecimal amount = costAmount.multiply(bigDecimal);
            return amount;
        }
    }

    @Override
    public void batchUpdateStatus(InsuranceStatusReq req) {
        List<Insurance> insurances = baseMapper.selectBatchIds(req.getIds());
        insurances.stream()
                .peek(insurance -> insurance.setStatus(req.getStatus()))
                .forEach(baseMapper::updateById);
    }

    @Override
    public InsuranceDTO detail(Long id) {
        return EntityUtil.convertBean(baseMapper.selectById(id), InsuranceDTO.class);
    }

    @Override
    public void updateDetail(InsuranceReq insuranceReq) {
        Insurance insurance = baseMapper.selectById(insuranceReq.getId());
        insurance.setName(insuranceReq.getName());
        insurance.setApplicableServices(insuranceReq.getApplicableServices());
        insurance.setProductTrait(insuranceReq.getProductTrait());
        insurance.setProductDescription(insuranceReq.getProductDescription());
        insurance.setSafeguardInterests(insuranceReq.getSafeguardInterests());
        insurance.setInsuranceNotice(insuranceReq.getInsuranceNotice());
        baseMapper.updateById(insurance);
    }

    /**
     * 根据业务类型查询
     *
     * @param applicableService
     * @return
     */
    @Override
    public List<InsuranceDTO> queryInsuranceDTO(String applicableService) {
        List<Insurance> insuranceList = baseMapper.selectList(new QueryWrapper<Insurance>().lambda()
                .eq(Insurance::getStatus, 1)
                .apply(applicableService != null, "FIND_IN_SET (" + applicableService + ",applicable_services)"));
        List<InsuranceDTO> insuranceDTOList = EntityUtil.copyList(insuranceList, InsuranceDTO.class);
        return insuranceDTOList;
    }

    @Override
    public List<InsurancePrdDTO> queryInsurancePrdDTO(String applicableService) {
        List<Insurance> insuranceList = baseMapper.selectList(new QueryWrapper<Insurance>().lambda()
                .eq(Insurance::getStatus, 1)
                .apply(applicableService != null, "FIND_IN_SET (" + applicableService + ",applicable_services)"));
        List<Long> idList = insuranceList.stream().map(Insurance::getId).collect(Collectors.toList());


        List<InsuranceProduct> productList = productMapper.selectList(
                new QueryWrapper<InsuranceProduct>().lambda().in(InsuranceProduct::getInsuranceId, idList));
        List<InsurancePrdDTO> prdDTOList = EntityUtil.copyList(productList, InsurancePrdDTO.class);
        return prdDTOList;
    }

    /**
     * 对内接口-承保接口
     *
     * @param insuranceUnderwritingReq
     * @return
     * @throws Exception
     */
    @Override
    public InsuranceInsuredDTO sendProposalContent(InsuranceUnderwritingReq insuranceUnderwritingReq) {
        log.info("【保险-投保】承保入口:{}", JSON.toJSONString(insuranceUnderwritingReq));
        ValidatorUtil.validate(insuranceUnderwritingReq);
        InsuranceInsuredDTO insuranceInsuredDTO = null;
        try {
            Insurance insurance = baseMapper.selectOne(new QueryWrapper<Insurance>().lambda()
                    .eq(Insurance::getId, insuranceUnderwritingReq.getInsuranceId())
                    .eq(Insurance::getIsDeleted, IsDeletedCode.NO.getCode())
                    .eq(Insurance::getStatus, 1)
                    .select(Insurance::getId, Insurance::getName, Insurance::getApiCode, Insurance::getRationType));
            if (null == insurance) {
                throw new BusinessException(SystemError.CUSTOM_ORDER_4028);
            }
            List<AcceptReq> acceptReqList = buildInsuranceTaiping(insuranceUnderwritingReq, insurance);
            // 调用第三方保险-承保
            log.info("【保险-投保】第三方承保入参:{}", JSON.toJSONString(acceptReqList));
            List<AcceptDTO> acceptDTOS = httpResult(acceptReqList);
            log.info("【保险-投保】第三方承保出参:{}", JSON.toJSONString(acceptDTOS));
            if (CollectionUtils.isEmpty(acceptDTOS)) {
                throw new BusinessException(SystemError.CUSTOM_ORDER_4026);
            }
            LocalDateTime localDateTime = LocalDateTime.now();
            UserDTO userDTO = sysUserService.queryCacheUser(insuranceUnderwritingReq.getUserId());
            if (userDTO == null) {
                throw new BusinessException(SystemError.USER_1002);
            }
            String insuranceReceiptNumber = generatorInsuranceReceiptNumber(localDateTime, userDTO);
            // 承保人
            AcceptReq acceptReq = acceptReqList.get(0);
            AppliGuRelatedParty appliGuRelatedPartyDto = acceptReq.getAppliGuRelatedPartyDto();
            /**
             * 生成印花税
             */
            String insuredName = StringUtils.isBlank(appliGuRelatedPartyDto.getInsuredName()) ? appliGuRelatedPartyDto.getInsuredEName() : appliGuRelatedPartyDto.getInsuredName();
            String startDate = acceptReq.getGuRiskDto().getStartDate();
            int length = appliGuRelatedPartyDto.getMobilePhone().length();
            String phoneNumber = appliGuRelatedPartyDto.getMobilePhone().substring(length - 4, length);
            BigDecimal received = insuranceUnderwritingReq.getTotalFee().multiply(new BigDecimal("0.0015"));
            received = received.setScale(2, BigDecimal.ROUND_HALF_UP);
            LevyRequest levyRequest = new LevyRequest();
            levyRequest.setReceiptNumber(insuranceReceiptNumber);
            levyRequest.setNameOfTravelerPayer(insuredName);
            levyRequest.setDepartureDate(startDate);
            levyRequest.setLast4DigitOfContactPhoneNumber(phoneNumber);
            levyRequest.setPremiumReceived(received.toString()); // 缴纳金额
            levyRequest.setBusinessType(SystemBusinessType.INSURANCE.getCode());
            levyRequest.setUserId(userDTO.getId());
            log.info("【保险-投保】调用印花税请求:{}", JSON.toJSONString(levyRequest));
            Result<LevyDTO> levyDTOResult = levyService.levyEFrank(levyRequest);
            log.info("【保险-投保】调用印花税响应:{}", JSON.toJSONString(levyDTOResult));
            if (!levyDTOResult.isSuccess() || levyDTOResult.getData() == null) {
                SystemError defined = SystemError.getDefined(levyDTOResult.getCode());
                throw new BusinessException(defined);
            }
            LevyDTO levyDTO = levyDTOResult.getData();
            String stampDutyPic = Base64.getEncoder().encodeToString(levyDTO.getLevystamp()); // 印花税图片
            /**
             * 生成供应商预订
             */
            SupplierOrderSystemInsuranceAddReq supplierOrderSystemInsuranceAddReq = new SupplierOrderSystemInsuranceAddReq();
            supplierOrderSystemInsuranceAddReq.setBusinessType(insuranceUnderwritingReq.getBusinessType());
            supplierOrderSystemInsuranceAddReq.setProductType(ProductType.API_PRODUCT.getCode());
            supplierOrderSystemInsuranceAddReq.setSupplierId(53479919123955712L); // 写死中国太平保险
            supplierOrderSystemInsuranceAddReq.setDepartmentId(userDTO.getDeptId());
            supplierOrderSystemInsuranceAddReq.setDepartment(userDTO.getDept());
            supplierOrderSystemInsuranceAddReq.setOrderType(1);
            supplierOrderSystemInsuranceAddReq.setSupplierOrderType("1");
            supplierOrderSystemInsuranceAddReq.setSaleType(SalesMethod.SINGLE_SALE.getCode());
            supplierOrderSystemInsuranceAddReq.setReserveTypeId(SupplierReserveTypeEnum.INSURANCE.getId());
            supplierOrderSystemInsuranceAddReq.setOriginalSaleNumber(userDTO.getDept());
            supplierOrderSystemInsuranceAddReq.setTotalFee(insuranceUnderwritingReq.getTotalFee());//业务订单成本价金额
            supplierOrderSystemInsuranceAddReq.setPayableAmount(insuranceUnderwritingReq.getTotalFee());//业务订单成本价金额
            supplierOrderSystemInsuranceAddReq.setSaleNumber(insuranceUnderwritingReq.getOrderNumber());//业务订单编号
            supplierOrderSystemInsuranceAddReq.setCurrencyId(Currency.HKD.getCode());//业务订单成本价币种
            supplierOrderSystemInsuranceAddReq.setCurrency(Currency.HKD.getCurrency());
            supplierOrderSystemInsuranceAddReq.setProductNumber(insuranceReceiptNumber);
            supplierOrderSystemInsuranceAddReq.setProductName(insurance.getName());
            // 供应商预订-保险信息
            SupplierSystemOrderInsuranceAddReq supplierSystemOrderInsuranceAddReq = new SupplierSystemOrderInsuranceAddReq();
            supplierOrderSystemInsuranceAddReq.setSupplierSystemOrderInsuranceAddReq(supplierSystemOrderInsuranceAddReq);
//        supplierSystemOrderInsuranceAddReq.setCustomerRemark("");

            List<SupplierSystemOrderInsuranceDetailAddReq> insuranceDetailAddReqList = new ArrayList<>();
            supplierSystemOrderInsuranceAddReq.setSupplierSystemOrderInsuranceDetailAddReqList(insuranceDetailAddReqList);

            SupplierSystemOrderInsuranceDetailAddReq insuranceDetailAddReq = new SupplierSystemOrderInsuranceDetailAddReq();
            insuranceDetailAddReqList.add(insuranceDetailAddReq);

            HashMap payUserJson = new HashMap(4);
            payUserJson.put("name", appliGuRelatedPartyDto.getInsuredName());
            payUserJson.put("eName", appliGuRelatedPartyDto.getInsuredEName());
            payUserJson.put("certificateType", appliGuRelatedPartyDto.getIdentifyType());
            payUserJson.put("certificateNumber", appliGuRelatedPartyDto.getIdentifyNumber());
            // 被保人
            List<HashMap> insureUserJson = new ArrayList<>();
            for (GuItemAcc guItemAcc : acceptReqList.get(0).getGuItemAcciListDtoList()) {
                HashMap item = new HashMap(4);
                item.put("name", guItemAcc.getClientCName());
                item.put("certificateType", guItemAcc.getIdentifyTypeA());
                item.put("certificateNumber", guItemAcc.getIdentifyNoA());
                insureUserJson.add(item);
            }
            insuranceDetailAddReq.setInsuranceNumber(generatorInsuranceNumber(localDateTime, userDTO));
            insuranceDetailAddReq.setInsuranceId(insuranceUnderwritingReq.getInsuranceId());
            insuranceDetailAddReq.setInsuranceName(insurance.getName());
            insuranceDetailAddReq.setPayUserJson(JSON.toJSONString(payUserJson));
            insuranceDetailAddReq.setInsuredUserJson(JSON.toJSONString(insureUserJson));
            insuranceDetailAddReq.setSingleFee(insuranceUnderwritingReq.getTotalFee());
            insuranceDetailAddReq.setTotalFee(insuranceUnderwritingReq.getTotalFee());

            log.info("【保险-投保】调用供应商预订请求,req:{},userId:{}", JSON.toJSONString(supplierOrderSystemInsuranceAddReq), insuranceUnderwritingReq.getUserId());
            Result<String> supplierResult = supplierOrderService.addSystemInsurance(supplierOrderSystemInsuranceAddReq, insuranceUnderwritingReq.getUserId());

            insuranceInsuredDTO = new InsuranceInsuredDTO();
            insuranceInsuredDTO.setAcceptDTOS(acceptDTOS);
            insuranceInsuredDTO.setInsuranceReceiptNumber(insuranceReceiptNumber);
            insuranceInsuredDTO.setStampDutyPic(stampDutyPic);
            insuranceInsuredDTO.setStampDutyAmount(received);
            insuranceInsuredDTO.setStampDutySupplierOrderNumber(levyDTOResult.getData().getSupplierOrderNumber());
        } catch (BusinessException e) {
            log.error("【保险-投保】调用保险预订失败,error:{}", e.getMessage(), e);
            throw new BusinessException(SystemError.getDefined(e.getCode()));
        } catch (Exception e) {
            log.error("【保险-投保】调用保险预订失败,error:{}", e.getMessage(), e);
            throw new BusinessException(SystemError.SUPPLIER_BOOKING_13702);
        }
        return insuranceInsuredDTO;
    }

    /**
     * 构建保险请求实体
     *
     * @param insuranceUnderwritingReq
     * @param insurance
     * @return
     */
    private List<AcceptReq> buildInsuranceTaiping(InsuranceUnderwritingReq insuranceUnderwritingReq, Insurance insurance) {
        List<AcceptReq> acceptReqList = new ArrayList<>();
        AcceptReq acceptReq = new AcceptReq();
        acceptReqList.add(acceptReq);
        AcceptUnderReq acceptUnderReq = insuranceUnderwritingReq.getAcceptReqList().get(0);
        String insuranceId = String.valueOf(insuranceUnderwritingReq.getInsuranceId());

        // 构建基本讯息
        BaseInfo guMainDto = new BaseInfo();
        guMainDto.setAgreementNo(PacificUtil.AGREEMENTNO);
        guMainDto.setIsElectronicPolicyInd("1");
        guMainDto.setEmailReceiverType("0");
        guMainDto.setIntermediaryCode(PacificUtil.INTERMEDIARYCODE);
        guMainDto.setSolutionCode(PacificUtil.SOLUTIONCODE);
        guMainDto.setOperatorCode(PacificUtil.OPERATORCODE);
        acceptReq.setGuMainDto(guMainDto);
        // 构建计划资讯列表
        List<PlanConsult> guItemAcciDetailDtoList = new ArrayList<>();
        acceptReq.setGuItemAcciDetailDtoList(guItemAcciDetailDtoList);
        PlanConsult planConsult = new PlanConsult();
        guItemAcciDetailDtoList.add(planConsult);

        planConsult.setItemDetailNo(insuranceId);
        planConsult.setRationType(String.valueOf(insurance.getRationType()));
        planConsult.setRemark("01");
        // 构建投保人资讯
        AppliGuRelatedParty appliGuRelatedParty = EntityUtil.copy(acceptUnderReq.getAppliGuRelatedPartyDto(), AppliGuRelatedParty.class);
        acceptReq.setAppliGuRelatedPartyDto(appliGuRelatedParty);
        appliGuRelatedParty.setInsuredAddress("通讯地址");
        // 构建被保人资讯列表
        List<GuItemAcc> guItemAccs = EntityUtil.copyList(acceptUnderReq.getGuItemAcciListDtoList(), GuItemAcc.class);
        for (GuItemAcc guItemAcc : guItemAccs) {
            guItemAcc.setItemDetailNo(insuranceId);
            guItemAcc.setRelationship("99");
            guItemAcc.setClientNo(CharUtil.getChar(6));
            //证件类型
//            String identifyTypeA = PacificUtil.getIdentifyType(guItemAcc.getCertificateTypeId());
//            guItemAcc.setIdentifyTypeA(identifyTypeA);
            //年龄类型
            String remark3 = PacificUtil.getAgeType(Integer.valueOf(guItemAcc.getAge()), insurance.getApiCode());// 年龄类型码表1-6
            guItemAcc.setRemark3(remark3);
        }
        acceptReq.setGuItemAcciListDtoList(guItemAccs);
        // 构建险别资讯
        RiskConsult riskConsult = new RiskConsult();
        riskConsult.setRiskCode(insurance.getApiCode());
        riskConsult.setStartDate(acceptUnderReq.getStartDate());
        riskConsult.setEndDate(acceptUnderReq.getEndDate());
        riskConsult.setStartPlace(acceptUnderReq.getStartPlace());
        riskConsult.setEndPlace(acceptUnderReq.getEndPlace());
        acceptReq.setGuRiskDto(riskConsult);
        // 构建其他信息
        OtherInfo otherInfo = new OtherInfo();
        otherInfo.setSerialNo(CharUtil.getRandomStr(5));
        acceptReq.setOtherInfo(otherInfo);
        return acceptReqList;
    }

    /**
     * 生成保险收据单号，門市編號+員工編號+年後2位月日4位+B+時分秒6位+（S）
     * 例：XS01-C07884-200407-B-110008（S）
     *
     * @param localDateTime
     * @param userDTO
     * @return
     */
    private String generatorInsuranceReceiptNumber(LocalDateTime localDateTime, UserDTO userDTO) {
        String deptCode = userDTO.getDeptCode();
        String employeeNumber = userDTO.getEmployeeNumber();
        String date = DateUtil.fmt(localDateTime, "yyMMdd");
        String time = DateUtil.fmt(localDateTime, "HHmmss");
        StringBuilder sb = new StringBuilder();
        sb.append(deptCode).append("-").append(employeeNumber).append("-").append(date).append("-B-").append(time).append("（S）");
        return sb.toString().toUpperCase();
    }

    /**
     * 生成保险单号，門市編號+員工編號+年後2位月日4位+B+時分秒6位+（S）
     * 例：XS01-C07884-200407-B-110008（S）
     *
     * @param localDateTime
     * @param userDTO
     * @return
     */
    private String generatorInsuranceNumber(LocalDateTime localDateTime, UserDTO userDTO) {
        String deptCode = userDTO.getDeptCode();
        String employeeNumber = userDTO.getEmployeeNumber();
        String date = DateUtil.fmt(localDateTime, "yyMMdd");
        String randomNumber = String.valueOf((int) ((Math.random() * 9 + 1) * 100));
        StringBuffer sb = new StringBuffer();
        sb.append("I").append(deptCode + "-").append(employeeNumber + "-").append(date + "-").append(randomNumber);
        return sb.toString().toUpperCase();
    }

    /**
     * 对内接口-报价接口
     *
     * @param offerReq
     * @return
     * @throws Exception
     */
    @Override
    public OfferDTO acciQuotation(OfferReq offerReq) throws Exception {
        log.info("【保险-报价】报价入参:{}", JSON.toJSONString(offerReq));
        ValidatorUtil.validate(offerReq);
        Offer data = offerReq.getData();
        Insurance insurance = baseMapper.selectOne(new QueryWrapper<Insurance>().lambda()
                .eq(Insurance::getId, data.getInsuranceId())
                .eq(Insurance::getIsDeleted, IsDeletedCode.NO.getCode())
                .eq(Insurance::getStatus, 1));
        if (null == insurance) {
            // 保险不存在
            throw new BusinessException(SystemError.CUSTOM_ORDER_4028);
        }
        data.setRiskCode(insurance.getApiCode());
        data.setRationType(insurance.getRationType());
        OfferDTO offerDTO1 = HttpUtils.postRequest(tpProperties.getOfferUrl(),
                JSON.toJSONString(createRequest(offerReq)), new HashMap<String, String>() {{
                    put("Content-Type", "application/json");
                    put("language", "T");
                    put("channel", tpProperties.getChannel());
                }}, response -> {
                    HttpEntity entity = response.getEntity();
                    JSONObject jsonObject = JSON.parseObject(EntityUtils.toString(entity));
                    log.info("【保险-报价】报价jsonObject：{}", jsonObject);
                    try {
                        String result = RSAUtil.decryptByPrivateKey(jsonObject.getString("message_body"), tpProperties.getPrivateKey());
                        log.info("【保险-报价】报价result：{}", result);
                        OfferDTO offerDTO = JSON.toJavaObject(JSON.parseObject(result).getJSONObject("data"), OfferDTO.class);
                        return offerDTO;
                    } catch (Exception e) {
                        log.error("【保险-报价】第三方接口解析失败：{}", e.getMessage(), e);
                    }
                    return null;
                });
        if (null != offerDTO1) {
            InsuranceProduct insuranceProduct = productMapper.selectOne(new QueryWrapper<InsuranceProduct>().lambda()
                    .eq(InsuranceProduct::getInsuranceId, offerReq.getData().getInsuranceId())
                    .eq(InsuranceProduct::getIsDeleted, IsDeletedCode.NO.getCode()));
            BigDecimal increasePrice = getIncreasePrice(offerDTO1.getPremium(), insuranceProduct);
            offerDTO1.setPremium(increasePrice);
        }
        return offerDTO1;
    }

    /**
     * 退保接口
     *
     * @param cancelReq
     * @return
     * @throws Exception
     */
    @Override
    public List<CancelDTO> policyCancel(List<CancelReq> cancelReq) throws Exception {
        return HttpUtils.postRequest(tpProperties.getCancelUrl(),
                JSON.toJSONString(createRequest(cancelReq)), new HashMap<String, String>() {{
                    put("Content-Type", "application/json");
                    put("language", "T");
                    put("channel", tpProperties.getChannel());
                }}, response -> {
                    HttpEntity entity = response.getEntity();
                    JSONObject jsonObject = JSON.parseObject(EntityUtils.toString(entity));
                    System.out.println("退保jsonObject" + jsonObject);
                    try {
                        String result = RSAUtil.decryptByPrivateKey(jsonObject.getString("message_body"), tpProperties.getPrivateKey());
                        System.out.println("退保result" + result);
                        return JSON.parseObject(result)
                                .getJSONArray("data")
                                .stream()
                                .map(item -> JSON.parseObject(JSON.toJSONString(item), CancelDTO.class))
                                .collect(Collectors.toList());
                    } catch (Exception e) {
                        log.error("第三方接口解析失败：" + e.getMessage());
                    }
                    return Lists.newArrayList();
                });
    }


    private List<AcceptDTO> httpResult(List<AcceptReq> acceptReq) throws Exception {
        return HttpUtils.postRequest(tpProperties.getAcceptUrl(),
                JSON.toJSONString(createRequest(acceptReq)), new HashMap<String, String>() {{
                    put("Content-Type", "application/json");
                    put("language", "T");
                    put("channel", tpProperties.getChannel());
                }}, response -> {
                    HttpEntity entity = response.getEntity();
                    String entityStr = EntityUtils.toString(entity);
                    log.info("【保险-投保】jsonObject:{}", entityStr);
                    JSONObject jsonObject = JSON.parseObject(entityStr);
                    try {
                        String result = RSAUtil.decryptByPrivateKey(jsonObject.getString("message_body"), tpProperties.getPrivateKey());
                        log.info("【保险-投保】result:{}", result);
                        return JSON.parseObject(result)
                                .getJSONArray("data")
                                .stream()
                                .map(item -> JSON.parseObject(JSON.toJSONString(item), AcceptDTO.class))
                                .collect(Collectors.toList());
                    } catch (Exception e) {
                        log.error("【保险-投保】第三方接口解析失败：{}", e.getMessage(), e);
                    }
                    return Lists.newArrayList();
                });
    }

    private Map<String, String> createRequest(Object obj) throws Exception {
        String rsaEn = RSAUtil.encryptByPublicKey(JSON.toJSONString(obj), tpProperties.getTpPublicKey());
        String sign = RSAUtil.sign(JSON.toJSONString(obj), tpProperties.getPrivateKey());

        return new HashMap<String, String>() {{
            put("message_body", rsaEn);
            put("signature", sign);
        }};
    }
}
